package gobelinmaker.client;

import com.esotericsoftware.kryonet.Connection;
import com.esotericsoftware.kryonet.Listener;
import gobelinmaker.data.BasicHoleData;
import gobelinmaker.data.CompiledKanava;
import gobelinmaker.data.HoleFinder;
import gobelinmaker.data.HoleFinderResult;
import gobelinmaker.data.HolePath;
import gobelinmaker.data.HolePathElement;
import gobelinmaker.data.Kanava;
import gobelinmaker.server.CameraColorAdjustmentChangeRequest;
import gobelinmaker.server.ByteArrayPartResponse;
import gobelinmaker.server.CameraCalibrationPointsChangeRequest;
import gobelinmaker.server.CameraCalibrationPointsResponse;
import gobelinmaker.server.CameraColorAdjustmentResponse;
import gobelinmaker.server.CameraImageRequest;
import gobelinmaker.server.CamerasListRequest;
import gobelinmaker.server.CamerasListResponse;
import gobelinmaker.server.ColorAdjustment;
import gobelinmaker.server.GobelinServer;
import gobelinmaker.server.JobRequest;
import gobelinmaker.server.JobResponse;
import gobelinmaker.server.LightControlRequest;
import gobelinmaker.server.MotorControlRequest;
import gobelinmaker.server.NeedleCalibrationPointChangeRequest;
import gobelinmaker.server.NeedleCalibrationPointResponse;
import gobelinmaker.server.ServerCamera;
import gobelinmaker.server.ServerData;
import gobelinmaker.server.ServerStateResponse;
import gobelinmaker.server.ServerStates;
import gobelinmaker.server.StopDiscoveringHolesRequest;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JSlider;
import javax.swing.JSpinner;
import javax.swing.JToggleButton;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.imgscalr.Scalr;

/**
 * Szerver kezelését megvalósító panel osztálya.
 *
 * @author imruf84
 */
public class ServerPanel extends javax.swing.JPanel {

    /**
     * Szerver adatai.
     */
    private final ServerData sd;
    /**
     * Kép megjelenítésére szolgáló panel.
     */
    private final ImagePane imagePane = new ImagePane();
    /**
     * Szerver által küldött legutóbbi eredeti kép.
     */
    private final AtomicReference<BufferedImage> originalImage = new AtomicReference<>(new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB));
    /**
     * Kameraképek ideiglenes tárolója.
     */
    private final HashMap<Integer, byte[]> imageTemp = new HashMap<>();
    /**
     * Lyukfelismerő.
     */
    private final HoleFinder holeFinder = new HoleFinder();
    /**
     * Szétkapcsolási kérelem.
     */
    private AtomicBoolean toDisconnect = new AtomicBoolean(false);
    /**
     * Tű kalibrációs helye.
     */
    private Point2D needleCalibrationPoint = new Point2D.Double();
    /**
     * Felderített lyukak megjelenítésére szolgáló ablak.
     */
    private final DiscoveredHolesFrame discoveredHolesFrame;
    /**
     * Kamera kalibrációs pontjai.
     */
    private Point2D cameraCalibrationPoints[] = {new Point2D.Double(), new Point2D.Double(), new Point2D.Double(), new Point2D.Double()};
    /**
     * Kamera kalibráció számlálója.
     */
    private final AtomicInteger cameraCalibrationCounter = new AtomicInteger();
    /**
     * Kamera fényereje.
     */
    private float brightness = 0;
    /**
     * Kamera kontrasztja.
     */
    private float contrast = 100;
    /**
     * Kamera fókusza.
     */
    private float focus = -1;
    /**
     * Küldendő kanava.
     */
    private final CompiledKanava kanavaToSend = new CompiledKanava();
    /**
     * Egy adagban küldendő lyukak számának maximuma.
     */
    private final AtomicInteger holesToSendCount = new AtomicInteger(10);

    /**
     * Creates new form ServerPanel
     *
     * @param sd szerver adatai
     */
    public ServerPanel(ServerData sd) {
        initComponents();
        this.sd = sd;

        // Mivel nem a kütyüről kapja a jelet, ezért felesleges megjeleníteni a fényekkel kapcsolatos vezérlő elemeket.
        this.lightsPanel.setVisible(false);

        final Component c = this;

        // Felderített lyukak ablakának létrehozása, beállítása.
        discoveredHolesFrame = new DiscoveredHolesFrame(this);
        discoveredHolesFrame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                e.getWindow().setVisible(false);
                showHolesToggleButton.setSelected(false);
            }
        });

        // Görgetés sebességének a meghatározása.
        this.optionsScrollPane.getHorizontalScrollBar().setUnitIncrement(GobelinClientGUI.WHEEL_SCROLL_SIZE);
        this.optionsScrollPane.getVerticalScrollBar().setUnitIncrement(GobelinClientGUI.WHEEL_SCROLL_SIZE);

        viewAllMarksCheckBox.setSelected(true);

        // Kép panel létrehozása, beállítása.
        this.imagePane.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent me) {
                // Tűkalibrációs mód kezelése.
                if (isNeedleCalibrationMode()) {
                    leaveNeedleCalibrationMode();

                    Rectangle r = imagePane.getImageRectangle();
                    Point2D p = new Point2D.Double(
                            Math.min(Math.max(0, me.getPoint().getX() - r.x), r.width) / r.width,
                            Math.min(Math.max(0, me.getPoint().getY() - r.y), r.height) / r.height);

                    // Új pont küldése a szervernek.
                    NeedleCalibrationPointChangeRequest ncpcr = new NeedleCalibrationPointChangeRequest();
                    ncpcr.cameraID = getCurrentCameraID();
                    ncpcr.p = p;
                    getConnection().sendTCP(ncpcr);

                    return;
                }

                // Kamera kalibrációs mód kezelése.
                if (isCameraCalibrationMode()) {
                    // Tárolunk a soron következő pontot.
                    Rectangle r = imagePane.getImageRectangle();
                    Point2D p = new Point2D.Double(
                            Math.min(Math.max(0, me.getPoint().getX() - r.x), r.width) / r.width,
                            Math.min(Math.max(0, me.getPoint().getY() - r.y), r.height) / r.height);
                    cameraCalibrationPoints[cameraCalibrationCounter.get()].setLocation(p);

                    // Számláló tesztelése.
                    synchronized (cameraCalibrationCounter) {
                        if (3 < cameraCalibrationCounter.incrementAndGet()) {
                            // Kalibrációs mód elhagyása.
                            leaveCameraCalibrationMode();

                            // Adatok küldése.
                            CameraCalibrationPointsChangeRequest ccpcr = new CameraCalibrationPointsChangeRequest();
                            ccpcr.cameraID = getCurrentCameraID();
                            ccpcr.pTL = cameraCalibrationPoints[0];
                            ccpcr.pTR = cameraCalibrationPoints[1];
                            ccpcr.pBR = cameraCalibrationPoints[2];
                            ccpcr.pBL = cameraCalibrationPoints[3];
                            getConnection().sendTCP(ccpcr);
                        }

                    }

                    return;
                }
            }
        });
        this.mainSplitPane.setLeftComponent(this.imagePane);

        // Események beállítása.
        this.sd.getConnection().addListener(new Listener() {
            @Override
            public void received(Connection connection, Object o) {

                // Ha szétkapcsolási kérelem van, akkor bontjuk a kapcsolatot és kilépünk.
                if (toDisconnect.get()) {
                    connection.close();
                    return;
                }

                updateOptionsPanelSize();

                // Szerver állapota érkezett.
                if (o instanceof ServerStateResponse) {
                    ServerStateResponse ssr = (ServerStateResponse) o;

                    // Kamera fényforrásának az állapotának a frissítése.
                    cameraLightCheckBox.setSelected(ssr.cameraLight);
                    // Rendszer hőmérséklete.
                    coreTemperatureLabel.setText("Hőmérséklet:" + (Double.isNaN(ssr.coreTemperature) ? "-" : (int) Math.floor(ssr.coreTemperature / 1000.0) + "\u00b0C"));
                    // Aktuális munkafolyamat adatai.
                    jobDataLabel.setText("Munka:" + (ssr.jobName.isEmpty() ? "-" : ssr.jobName));
                    serverStateLabel.setText(ServerStates.getStateReadableName(ssr.state));
                    jobProgressLabel.setText(ssr.progress.isNaN() ? "" : (new DecimalFormat("0.00").format(ssr.progress) + "%"));
                    // Motorokkal kapcsolatos adatok.
                    motorLocationsLabel.setText("X:" + ssr.motorLocations[0] + " Y:" + ssr.motorLocations[2]);
                    discoveredHolesFrame.getHolesPanel().getNeedleComponent().setPosition(ssr.motorLocations[0], ssr.motorLocations[2]);

                    // Munkafolyamat gombjainak a frissítése.
                    // Ha folyamatban van küldés vagy törlés, akkor mindent tiltunk.
                    if (ssr.state.equals(ServerStates.JOB_CREATE) || ssr.state.equals(ServerStates.JOB_REMOVE)) {
                        newJobButton.setEnabled(false);
                        removeJobButton.setEnabled(false);
                        return;
                    }

                    // Egyébként a jelenlegi helyzet szerint frissítünk mindent.
                    if (ssr.jobName.isEmpty()) {
                        newJobButton.setEnabled(true);
                        removeJobButton.setEnabled(false);
                    } else {
                        newJobButton.setEnabled(false);
                        removeJobButton.setEnabled(true);
                    }

                    return;
                }

                // Bájttömbdarab (pl kép) érkezett.
                if (o instanceof ByteArrayPartResponse) {
                    ByteArrayPartResponse bapr = (ByteArrayPartResponse) o;

                    // Rész tárolása.
                    getImageTemp().put(bapr.part, bapr.data);

                    // Ha minden rész a helyén van, akkor megjelenítjük a képet.
                    if (bapr.count == getImageTemp().keySet().size()) {
                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
                        for (int i = 1; i <= bapr.count; i++) {
                            try {
                                baos.write(getImageTemp().get(i));
                            } catch (IOException | NullPointerException ex) {
                                System.err.println(ex.getLocalizedMessage());
                            }
                        }

                        // Átalakítás képpé.
                        InputStream in = new ByteArrayInputStream(baos.toByteArray());
                        try {
                            // Jelöljük, hogy adat érkezett (az indikátorral).
                            String cc = "/";
                            switch (receivingDataLabel.getText()) {
                                case "/":
                                    cc = "\\";
                                    break;
                            }
                            receivingDataLabel.setText(cc);

                            BufferedImage image = ImageIO.read(in);

                            // Tároljuk az eredeti képet is, mert ezen még nem szerepelnek a jelölések.
                            synchronized (originalImage) {
                                originalImage.set(image);
                            }

                            // Transzformáljuk ha szükséges.
                            if (cameraTransformedImageCheckBox.isSelected()) {
                                image = ServerCamera.transformImage(image, cameraCalibrationPoints);
                            }

                            // Kép színbeállítása.
                            image = ColorAdjustment.applyBrightnessAndContrast(image, contrast, brightness);

                            boolean tr = cameraTransformedImageCheckBox.isSelected();

                            // Lyukak felismerése.
                            boolean holeFinderNeeded = getCurrentCameraID().equals(GobelinServer.CAMERA_KANAVA_ID);
                            if (holeFinderNeeded) {
                                HoleFinderResult hfr = holeFinder.findHoles(image);

                                // Kép megjelenítése.
                                imagePane.setDrawImage(hfr.getOriginalImage(), false);

                                // Komponensek berajzolása, majd az új kép megjelenítése.
                                imagePane.setDrawImage(
                                        hfr.drawComponents(
                                                imagePane.getImage(),
                                                tr && viewHoleFoundMarksCheckBox.isSelected() ? Color.yellow : null,
                                                tr && viewHoleCalcMarksCheckBox.isSelected() ? Color.red : null,
                                                tr && viewLineMarksCheckBox.isSelected() ? Color.green : null,
                                                needleCalibrationPoint,
                                                tr && viewNeedleMarkCheckBox.isSelected() ? Color.magenta : null,
                                                cameraCalibrationPoints,
                                                !tr ? Color.magenta : null),
                                        true);
                            } else {
                                // Kép megjelenítése.
                                imagePane.setDrawImage(image, true);
                            }

                        } catch (IOException ex) {
                            System.err.println(ex.getLocalizedMessage());
                        } catch (NoninvertibleTransformException | CloneNotSupportedException ex) {
                            System.err.println(ex.getLocalizedMessage());
                        }

                        // Igény küldése új képre.
                        getNewCameraImage();
                    }
                    return;
                }

                // Kamerák listája érkezett.
                if (o instanceof CamerasListResponse) {

                    CamerasListResponse clr = (CamerasListResponse) o;

                    // Kamerák listájának létrehozása.
                    JRadioButton rbdef = null;
                    JRadioButton rb;
                    for (String ID : clr.keySet()) {
                        rb = new JRadioButton(clr.get(ID));
                        rb.setActionCommand(ID);
                        rb.addActionListener(new ActionListener() {
                            @Override
                            public void actionPerformed(ActionEvent ae) {
                                getNewCameraImage();
                            }
                        });
                        camerasPanel.add(rb);
                        camerasGroup.add(rb);

                        // A kanava kamera lesz az alapértelmezett.
                        if (null == rbdef || ID.equals(GobelinServer.CAMERA_KANAVA_ID)) {
                            rbdef = rb;
                        }
                    }

                    // Lista frissítése (kirajzolása).
                    camerasPanel.updateUI();

                    if (null != rbdef) {
                        rbdef.setSelected(true);
                    }

                    // Kamerakép kérése.
                    getNewCameraImage();

                    return;
                }

                // Adott kamera tű kalibrációs pozíciója érkezett.
                if (o instanceof NeedleCalibrationPointResponse) {

                    NeedleCalibrationPointResponse ncp = (NeedleCalibrationPointResponse) o;

                    // Új pont tárolása.
                    needleCalibrationPoint.setLocation(ncp.p);

                    return;
                }

                // Adott kamera beállítás érkezett.
                if (o instanceof CameraColorAdjustmentResponse) {

                    CameraColorAdjustmentResponse ccar = (CameraColorAdjustmentResponse) o;

                    // Új beállítások tárolása.
                    brightness = ccar.brightness;
                    contrast = ccar.contrast;
                    focus = ccar.focus;

                    return;
                }

                // Adott kamera tű kalibrációs pozíciója érkezett.
                if (o instanceof CameraCalibrationPointsResponse) {

                    // Ha épp kalibrációs módban vagyunk akkor kilépünk.
                    if (isCameraCalibrationMode()) {
                        return;
                    }

                    CameraCalibrationPointsResponse ccp = (CameraCalibrationPointsResponse) o;

                    // Új pont tárolása.
                    cameraCalibrationPoints[0].setLocation(ccp.pTL);
                    cameraCalibrationPoints[1].setLocation(ccp.pTR);
                    cameraCalibrationPoints[2].setLocation(ccp.pBR);
                    cameraCalibrationPoints[3].setLocation(ccp.pBL);

                    return;
                }

                // Munkafolyamattal kapcsolatos válasz élrkezett.
                if (o instanceof JobResponse) {

                    JobResponse jrs = (JobResponse) o;

                    // Ha hiba van, akkor megjelenítjük.
                    if (jrs.hasError) {
                        Dialogs.showErrorMessageDialog(c, jrs.errorMessage);
                        kanavaToSend.clear();
                        return;
                    }

                    // Ha van még küldendő adat akkor küldjük.
                    if (jrs.dataNeeded) {
                        synchronized (kanavaToSend) {
                            if (!kanavaToSend.isEmpty()) {
                                JobRequest jr = new JobRequest();

                                HolePath hp = kanavaToSend.getFirst();
                                HolePathElement hpe = hp.getFirst();

                                // Első elem esetén a fonal adatait is küldjük.
                                if (0 == hpe.index) {
                                    jr.woolData = hp.toBasicWoolData();
                                }

                                // Lyuk(ak) adatai.
                                int size = Math.min(kanavaToSend.size(), holesToSendCount.get());
                                jr.holeData = new BasicHoleData[size];
                                for (int i = 0; i < size; i++) {
                                    jr.holeData[i] = hp.pop().toBasicHoledata(hp);
                                }

                                // Ha nincs több eleme akkor töröljük a fonalat.
                                if (hp.isEmpty()) {
                                    kanavaToSend.pop();
                                }

                                // Ha nincs több adat, akkor jelezzük.
                                if (kanavaToSend.isEmpty()) {
                                    jr.finished = true;
                                }

                                // Folyamat aktualizálása.
                                jr.total = kanavaToSend.getStoredTotalCount();
                                jr.left = kanavaToSend.getTotalCount();

                                // Adatok küldése.
                                getConnection().sendTCP(jr);

                                return;
                            }
                        }

                        return;
                    }

                    // Munkamenet sikeresen létrehozva.
                    if (jrs.jobStored) {
                        return;
                    }

                    // Munkamenet sikeresen törölve.
                    if (jrs.jobRemoved) {
                        return;
                    }

                    return;
                }

            }
        });

        // Kamerák listájának a lekérdezése.
        this.getCamerasList();

        // Panel méretének a megfelelőre méretezése.
        updateOptionsPanelSize();
    }

    /**
     * Panel méretének frissítése a változó tartalomhoz (a görgetősávokkal van
     * gond új elemek hozzáadásakor).
     */
    private void updateOptionsPanelSize() {

        optionsPanel.setPreferredSize(new Dimension(optionsPanel.getPreferredSize().width, optionsPanel.getComponent(optionsPanel.getComponentCount() - 1).getY() + optionsPanel.getComponent(optionsPanel.getComponentCount() - 1).getHeight()));
        optionsPanel.updateUI();
    }

    /**
     * Kapcsolat lekérdezése.
     *
     * @return kapcsolat
     */
    public Connection getConnection() {
        return this.sd.getConnection();
    }

    /**
     * Kép ideiglenes tárolójának a lekérdezése.
     *
     * @return ideiglenes tároló
     */
    private HashMap<Integer, byte[]> getImageTemp() {
        return this.imageTemp;
    }

    /**
     * Kapcsolat bontásának kezdeményezése.
     */
    public void disconnect() {
        toDisconnect.set(true);
    }

    /**
     * Új kamerakép kérése.
     */
    private void getNewCameraImage() {
        // Ideiglenes állomány törlése.
        this.getImageTemp().clear();

        // Igény küldése.
        CameraImageRequest cir = new CameraImageRequest();
        cir.cameraID = this.getCurrentCameraID();
        getConnection().sendTCP(cir);
    }

    /**
     * Aktuális kamera azonosítójának a lekérdezése.
     *
     * @return aktuális kamera azonosítója
     */
    private String getCurrentCameraID() {
        return camerasGroup.getSelection().getActionCommand();
    }

    /**
     * Kamerák listájának a lekérdezése.
     */
    private void getCamerasList() {
        this.getConnection().sendTCP(new CamerasListRequest());
    }

    /**
     * Tűkalibrációs módban vagyunk.
     *
     * @return igaz esetén tűkalibrációs módban vagyunk
     */
    private boolean isNeedleCalibrationMode() {
        return needleCalibrationButton.isSelected();
    }

    /**
     * Tűkalibrációs mód elhagyása.
     */
    private void leaveNeedleCalibrationMode() {
        this.needleCalibrationButton.setSelected(false);
    }

    /**
     * Kamera kalibrációs módban vagyunk.
     *
     * @return igaz esetén kamerakalibrációs módban vagyunk.
     */
    public boolean isCameraCalibrationMode() {
        return cameraCalibrationToggleButton.isSelected();
    }

    /**
     * Kamerakalibrációs mód elhagyása.
     */
    public void leaveCameraCalibrationMode() {

        this.cameraCalibrationToggleButton.setSelected(false);
        cameraCalibrationCounter.set(0);
    }

    /**
     * Letapogatott lyukak megjelenítését végző ablak bezárása.
     */
    public void closeDiscoveredHolesWindow() {
        discoveredHolesFrame.dispose();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        camerasGroup = new javax.swing.ButtonGroup();
        mainSplitPane = new javax.swing.JSplitPane();
        optionsScrollPane = new javax.swing.JScrollPane();
        optionsPanel = new javax.swing.JPanel();
        viewsPanel = new javax.swing.JPanel();
        viewAllMarksCheckBox = new javax.swing.JCheckBox();
        jSeparator1 = new javax.swing.JSeparator();
        viewHoleFoundMarksCheckBox = new javax.swing.JCheckBox();
        viewLineMarksCheckBox = new javax.swing.JCheckBox();
        viewHoleCalcMarksCheckBox = new javax.swing.JCheckBox();
        viewNeedleMarkCheckBox = new javax.swing.JCheckBox();
        camerasPanel = new javax.swing.JPanel();
        cameraTransformedImageCheckBox = new javax.swing.JCheckBox();
        cameraCalibrationToggleButton = new javax.swing.JToggleButton();
        brightnessContrastButton = new javax.swing.JButton();
        controlPanel = new javax.swing.JPanel();
        jPanel3 = new javax.swing.JPanel();
        contControlCheckBox = new javax.swing.JCheckBox();
        jPanel4 = new javax.swing.JPanel();
        controlButtonsPanel = new javax.swing.JPanel();
        closeHeadToggleButton = new javax.swing.JToggleButton();
        upStepToggleButton = new javax.swing.JToggleButton();
        openHeadToggleButton = new javax.swing.JToggleButton();
        leftStepToggleButton = new javax.swing.JToggleButton();
        downStepToggleButton = new javax.swing.JToggleButton();
        rightStepToggleButton = new javax.swing.JToggleButton();
        jPanel7 = new javax.swing.JPanel();
        snapButtonsPanel = new javax.swing.JPanel();
        jPanel5 = new javax.swing.JPanel();
        upSnapButton = new javax.swing.JButton();
        jPanel6 = new javax.swing.JPanel();
        leftSnapButton = new javax.swing.JButton();
        closestSnapButton = new javax.swing.JButton();
        rightSnapButton = new javax.swing.JButton();
        jPanel8 = new javax.swing.JPanel();
        downSnapButton = new javax.swing.JButton();
        jPanel9 = new javax.swing.JPanel();
        jPanel10 = new javax.swing.JPanel();
        jPanel11 = new javax.swing.JPanel();
        discoverHolesButton = new javax.swing.JButton();
        stopDiscoveringHolesButton = new javax.swing.JButton();
        showHolesToggleButton = new javax.swing.JToggleButton();
        needleCalibrationPanel = new javax.swing.JPanel();
        needleCalibrationButton = new javax.swing.JToggleButton();
        lightsPanel = new javax.swing.JPanel();
        cameraLightCheckBox = new javax.swing.JCheckBox();
        jobPanel = new javax.swing.JPanel();
        newJobButton = new javax.swing.JButton();
        removeJobButton = new javax.swing.JButton();
        informationPanel = new javax.swing.JPanel();
        receivingDataLabel = new javax.swing.JLabel();
        jLabel5 = new javax.swing.JLabel();
        coreTemperatureLabel = new javax.swing.JLabel();
        jLabel1 = new javax.swing.JLabel();
        jobDataLabel = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        serverStateLabel = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jobProgressLabel = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        motorLocationsLabel = new javax.swing.JLabel();

        setMinimumSize(new java.awt.Dimension(400, 400));
        setPreferredSize(new java.awt.Dimension(400, 400));
        setLayout(new java.awt.BorderLayout());

        mainSplitPane.setResizeWeight(1.0);
        mainSplitPane.setMinimumSize(new java.awt.Dimension(400, 400));
        mainSplitPane.setPreferredSize(new java.awt.Dimension(400, 400));

        optionsScrollPane.setBorder(null);
        optionsScrollPane.setMinimumSize(new java.awt.Dimension(190, 400));
        optionsScrollPane.setPreferredSize(new java.awt.Dimension(190, 400));

        optionsPanel.setMinimumSize(new java.awt.Dimension(150, 400));
        optionsPanel.setPreferredSize(new java.awt.Dimension(150, 400));

        viewsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Jelölők"));
        viewsPanel.setLayout(new javax.swing.BoxLayout(viewsPanel, javax.swing.BoxLayout.PAGE_AXIS));

        viewAllMarksCheckBox.setText("Mind");
        viewAllMarksCheckBox.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                viewAllMarksCheckBoxStateChanged(evt);
            }
        });
        viewsPanel.add(viewAllMarksCheckBox);
        viewsPanel.add(jSeparator1);

        viewHoleFoundMarksCheckBox.setText("Felismert lyukak");
        viewsPanel.add(viewHoleFoundMarksCheckBox);

        viewLineMarksCheckBox.setText("Egyenesek");
        viewsPanel.add(viewLineMarksCheckBox);

        viewHoleCalcMarksCheckBox.setText("Kiszámolt lyukak");
        viewsPanel.add(viewHoleCalcMarksCheckBox);

        viewNeedleMarkCheckBox.setText("Tű helye");
        viewsPanel.add(viewNeedleMarkCheckBox);

        camerasPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Kamerák"));
        camerasPanel.setLayout(new java.awt.GridLayout(0, 1));

        cameraTransformedImageCheckBox.setSelected(true);
        cameraTransformedImageCheckBox.setText("Transzformált kép");
        camerasPanel.add(cameraTransformedImageCheckBox);

        cameraCalibrationToggleButton.setText("Kalibrálás...");
        camerasPanel.add(cameraCalibrationToggleButton);

        brightnessContrastButton.setText("Beállítások...");
        brightnessContrastButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                brightnessContrastButtonActionPerformed(evt);
            }
        });
        camerasPanel.add(brightnessContrastButton);

        controlPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Vezérlés"));
        controlPanel.setLayout(new java.awt.BorderLayout());

        jPanel3.setLayout(new java.awt.BorderLayout());

        contControlCheckBox.setText("Folyamatos");
        jPanel3.add(contControlCheckBox, java.awt.BorderLayout.CENTER);

        controlPanel.add(jPanel3, java.awt.BorderLayout.PAGE_START);

        jPanel4.setLayout(new java.awt.BorderLayout());

        controlButtonsPanel.setLayout(new java.awt.GridLayout(2, 3));

        closeHeadToggleButton.setText("↦↤");
        closeHeadToggleButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                closeHeadToggleButtonActionPerformed(evt);
            }
        });
        controlButtonsPanel.add(closeHeadToggleButton);

        upStepToggleButton.setMnemonic(KeyEvent.VK_UP);
        upStepToggleButton.setText("↑");
        upStepToggleButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                upStepToggleButtonActionPerformed(evt);
            }
        });
        controlButtonsPanel.add(upStepToggleButton);

        openHeadToggleButton.setText("↤↦");
        openHeadToggleButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openHeadToggleButtonActionPerformed(evt);
            }
        });
        controlButtonsPanel.add(openHeadToggleButton);

        leftStepToggleButton.setMnemonic(KeyEvent.VK_LEFT);
        leftStepToggleButton.setText("←");
        leftStepToggleButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                leftStepToggleButtonActionPerformed(evt);
            }
        });
        controlButtonsPanel.add(leftStepToggleButton);

        downStepToggleButton.setMnemonic(KeyEvent.VK_DOWN);
        downStepToggleButton.setText("↓");
        downStepToggleButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                downStepToggleButtonActionPerformed(evt);
            }
        });
        controlButtonsPanel.add(downStepToggleButton);

        rightStepToggleButton.setMnemonic(KeyEvent.VK_RIGHT);
        rightStepToggleButton.setText("→");
        rightStepToggleButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                rightStepToggleButtonActionPerformed(evt);
            }
        });
        controlButtonsPanel.add(rightStepToggleButton);

        jPanel4.add(controlButtonsPanel, java.awt.BorderLayout.PAGE_START);

        jPanel7.setMinimumSize(new java.awt.Dimension(0, 10));
        jPanel7.setPreferredSize(new java.awt.Dimension(0, 10));

        javax.swing.GroupLayout jPanel7Layout = new javax.swing.GroupLayout(jPanel7);
        jPanel7.setLayout(jPanel7Layout);
        jPanel7Layout.setHorizontalGroup(
            jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 0, Short.MAX_VALUE)
        );
        jPanel7Layout.setVerticalGroup(
            jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 0, Short.MAX_VALUE)
        );

        jPanel4.add(jPanel7, java.awt.BorderLayout.CENTER);

        snapButtonsPanel.setLayout(new java.awt.GridLayout(0, 3));

        jPanel5.setLayout(new javax.swing.BoxLayout(jPanel5, javax.swing.BoxLayout.LINE_AXIS));
        snapButtonsPanel.add(jPanel5);

        upSnapButton.setText("↥");
        upSnapButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                upSnapButtonActionPerformed(evt);
            }
        });
        snapButtonsPanel.add(upSnapButton);

        jPanel6.setLayout(new javax.swing.BoxLayout(jPanel6, javax.swing.BoxLayout.LINE_AXIS));
        snapButtonsPanel.add(jPanel6);

        leftSnapButton.setText("↤");
        leftSnapButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                leftSnapButtonActionPerformed(evt);
            }
        });
        snapButtonsPanel.add(leftSnapButton);

        closestSnapButton.setText("O");
        closestSnapButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                closestSnapButtonActionPerformed(evt);
            }
        });
        snapButtonsPanel.add(closestSnapButton);

        rightSnapButton.setText("↦");
        rightSnapButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                rightSnapButtonActionPerformed(evt);
            }
        });
        snapButtonsPanel.add(rightSnapButton);

        jPanel8.setLayout(new javax.swing.BoxLayout(jPanel8, javax.swing.BoxLayout.LINE_AXIS));
        snapButtonsPanel.add(jPanel8);

        downSnapButton.setText("↧");
        downSnapButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                downSnapButtonActionPerformed(evt);
            }
        });
        snapButtonsPanel.add(downSnapButton);

        jPanel9.setLayout(new javax.swing.BoxLayout(jPanel9, javax.swing.BoxLayout.LINE_AXIS));
        snapButtonsPanel.add(jPanel9);

        jPanel4.add(snapButtonsPanel, java.awt.BorderLayout.PAGE_END);

        controlPanel.add(jPanel4, java.awt.BorderLayout.CENTER);

        jPanel10.setLayout(new java.awt.GridLayout(0, 1));

        jPanel11.setMinimumSize(new java.awt.Dimension(0, 10));
        jPanel11.setPreferredSize(new java.awt.Dimension(0, 10));

        javax.swing.GroupLayout jPanel11Layout = new javax.swing.GroupLayout(jPanel11);
        jPanel11.setLayout(jPanel11Layout);
        jPanel11Layout.setHorizontalGroup(
            jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 0, Short.MAX_VALUE)
        );
        jPanel11Layout.setVerticalGroup(
            jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 23, Short.MAX_VALUE)
        );

        jPanel10.add(jPanel11);

        discoverHolesButton.setText("Letapogatás...");
        discoverHolesButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                discoverHolesButtonActionPerformed(evt);
            }
        });
        jPanel10.add(discoverHolesButton);

        stopDiscoveringHolesButton.setText("Leállítás");
        stopDiscoveringHolesButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                stopDiscoveringHolesButtonActionPerformed(evt);
            }
        });
        jPanel10.add(stopDiscoveringHolesButton);

        showHolesToggleButton.setText("Eredmény...");
        showHolesToggleButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                showHolesToggleButtonActionPerformed(evt);
            }
        });
        jPanel10.add(showHolesToggleButton);

        controlPanel.add(jPanel10, java.awt.BorderLayout.PAGE_END);

        needleCalibrationPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Tű kalibrálása"));
        needleCalibrationPanel.setLayout(new java.awt.GridLayout(1, 0));

        needleCalibrationButton.setText("Kalibrálás...");
        needleCalibrationPanel.add(needleCalibrationButton);

        lightsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Fényforrások"));
        lightsPanel.setLayout(new java.awt.GridLayout(0, 1));

        cameraLightCheckBox.setText("Kamera");
        cameraLightCheckBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cameraLightCheckBoxActionPerformed(evt);
            }
        });
        lightsPanel.add(cameraLightCheckBox);

        jobPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Munkamenet"));
        jobPanel.setLayout(new java.awt.GridLayout(0, 1));

        newJobButton.setText("Új munka...");
        newJobButton.setEnabled(false);
        newJobButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                newJobButtonActionPerformed(evt);
            }
        });
        jobPanel.add(newJobButton);

        removeJobButton.setText("Törlés");
        removeJobButton.setEnabled(false);
        removeJobButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                removeJobButtonActionPerformed(evt);
            }
        });
        jobPanel.add(removeJobButton);

        javax.swing.GroupLayout optionsPanelLayout = new javax.swing.GroupLayout(optionsPanel);
        optionsPanel.setLayout(optionsPanelLayout);
        optionsPanelLayout.setHorizontalGroup(
            optionsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(camerasPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(viewsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(controlPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(needleCalibrationPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(lightsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jobPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        optionsPanelLayout.setVerticalGroup(
            optionsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(optionsPanelLayout.createSequentialGroup()
                .addComponent(viewsPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(camerasPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(controlPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(needleCalibrationPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(lightsPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jobPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        optionsScrollPane.setViewportView(optionsPanel);

        mainSplitPane.setRightComponent(optionsScrollPane);

        add(mainSplitPane, java.awt.BorderLayout.CENTER);

        java.awt.FlowLayout flowLayout1 = new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0);
        flowLayout1.setAlignOnBaseline(true);
        informationPanel.setLayout(flowLayout1);

        receivingDataLabel.setText("-");
        informationPanel.add(receivingDataLabel);

        jLabel5.setText(" | ");
        informationPanel.add(jLabel5);

        coreTemperatureLabel.setText("-");
        informationPanel.add(coreTemperatureLabel);

        jLabel1.setText(" | ");
        informationPanel.add(jLabel1);

        jobDataLabel.setText("-");
        informationPanel.add(jobDataLabel);

        jLabel2.setText(" | ");
        informationPanel.add(jLabel2);

        serverStateLabel.setText("-");
        informationPanel.add(serverStateLabel);

        jLabel3.setText(" | ");
        informationPanel.add(jLabel3);

        jobProgressLabel.setText("-");
        informationPanel.add(jobProgressLabel);

        jLabel4.setText(" | ");
        informationPanel.add(jLabel4);

        motorLocationsLabel.setText("-");
        informationPanel.add(motorLocationsLabel);

        add(informationPanel, java.awt.BorderLayout.PAGE_END);
    }// </editor-fold>//GEN-END:initComponents

    private void viewAllMarksCheckBoxStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_viewAllMarksCheckBoxStateChanged
        boolean b = viewAllMarksCheckBox.isSelected();
        viewHoleCalcMarksCheckBox.setSelected(b);
        viewHoleFoundMarksCheckBox.setSelected(b);
        viewLineMarksCheckBox.setSelected(b);
        viewNeedleMarkCheckBox.setSelected(b);
    }//GEN-LAST:event_viewAllMarksCheckBoxStateChanged


    private void rightStepToggleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rightStepToggleButtonActionPerformed

        JToggleButton btn = ((JToggleButton) evt.getSource());

        // Csak akkor küldünk, ha szükséges.
        if (this.contControlCheckBox.isSelected() || (!this.contControlCheckBox.isSelected() && btn.isSelected())) {
            MotorControlRequest mcr = new MotorControlRequest();
            mcr.continuous.x = this.contControlCheckBox.isSelected() && btn.isSelected();
            mcr.steps.x = this.contControlCheckBox.isSelected() || btn.isSelected() ? 1 : 0;
            this.getConnection().sendTCP(mcr);
        }

        // Ha nincs beállítva folyamatos vezérlés, akkor visszaléptetjük a gombot.
        if (!this.contControlCheckBox.isSelected()) {
            btn.setSelected(false);
        }

        // Szemközti irány letiltása.
        if (this.contControlCheckBox.isSelected()) {
            this.leftStepToggleButton.setEnabled(!btn.isSelected());
        }

    }//GEN-LAST:event_rightStepToggleButtonActionPerformed

    private void downStepToggleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_downStepToggleButtonActionPerformed
        JToggleButton btn = ((JToggleButton) evt.getSource());

        // Csak akkor küldünk, ha szükséges.
        if (this.contControlCheckBox.isSelected() || (!this.contControlCheckBox.isSelected() && btn.isSelected())) {
            MotorControlRequest mcr = new MotorControlRequest();
            mcr.continuous.y = this.contControlCheckBox.isSelected() && btn.isSelected();
            mcr.steps.y = this.contControlCheckBox.isSelected() || btn.isSelected() ? 1 : 0;
            this.getConnection().sendTCP(mcr);
        }

        // Ha nincs beállítva folyamatos vezérlés, akkor visszaléptetjük a gombot.
        if (!this.contControlCheckBox.isSelected()) {
            btn.setSelected(false);
        }

        // Szemközti irány letiltása.
        if (this.contControlCheckBox.isSelected()) {
            this.upStepToggleButton.setEnabled(!btn.isSelected());
        }

    }//GEN-LAST:event_downStepToggleButtonActionPerformed

    private void leftStepToggleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_leftStepToggleButtonActionPerformed
        JToggleButton btn = ((JToggleButton) evt.getSource());

        // Csak akkor küldünk, ha szükséges.
        if (this.contControlCheckBox.isSelected() || (!this.contControlCheckBox.isSelected() && btn.isSelected())) {
            MotorControlRequest mcr = new MotorControlRequest();
            mcr.continuous.x = this.contControlCheckBox.isSelected() && btn.isSelected();
            mcr.steps.x = this.contControlCheckBox.isSelected() || btn.isSelected() ? -1 : 0;
            this.getConnection().sendTCP(mcr);
        }

        // Ha nincs beállítva folyamatos vezérlés, akkor visszaléptetjük a gombot.
        if (!this.contControlCheckBox.isSelected()) {
            btn.setSelected(false);
        }

        // Szemközti irány letiltása.
        if (this.contControlCheckBox.isSelected()) {
            this.rightStepToggleButton.setEnabled(!btn.isSelected());
        }

    }//GEN-LAST:event_leftStepToggleButtonActionPerformed

    private void upStepToggleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_upStepToggleButtonActionPerformed
        JToggleButton btn = ((JToggleButton) evt.getSource());

        // Csak akkor küldünk, ha szükséges.
        if (this.contControlCheckBox.isSelected() || (!this.contControlCheckBox.isSelected() && btn.isSelected())) {
            MotorControlRequest mcr = new MotorControlRequest();
            mcr.continuous.y = this.contControlCheckBox.isSelected() && btn.isSelected();
            mcr.steps.y = this.contControlCheckBox.isSelected() || btn.isSelected() ? -1 : 0;
            this.getConnection().sendTCP(mcr);
        }

        // Ha nincs beállítva folyamatos vezérlés, akkor visszaléptetjük a gombot.
        if (!this.contControlCheckBox.isSelected()) {
            btn.setSelected(false);
        }

        // Szemközti irány letiltása.
        if (this.contControlCheckBox.isSelected()) {
            this.downStepToggleButton.setEnabled(!btn.isSelected());
        }

    }//GEN-LAST:event_upStepToggleButtonActionPerformed

    private void cameraLightCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cameraLightCheckBoxActionPerformed
        LightControlRequest lcr = new LightControlRequest();
        lcr.on = this.cameraLightCheckBox.isSelected();
        this.getConnection().sendTCP(lcr);
    }//GEN-LAST:event_cameraLightCheckBoxActionPerformed

    private void newJobButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newJobButtonActionPerformed

        final Component c = this;

        // Állomány kiválasztása.
        JFileChooser fc = new JFileChooser();
        fc.addChoosableFileFilter(new UncopressedFileFilter());
        fc.setFileFilter(new CopressedFileFilter());
        fc.setAcceptAllFileFilterUsed(false);

        int m = fc.showOpenDialog(this);
        if (m == JFileChooser.APPROVE_OPTION) {

            // Kanava megnyitása.
            String fileName = fc.getSelectedFile().getAbsolutePath();
            Kanava k = new Kanava(0, 0, false);
            try {
                k.open(fileName);
                synchronized (kanavaToSend) {
                    kanavaToSend.clear();
                    kanavaToSend.addAll(k.compile());
                    kanavaToSend.storeTotalCount();
                }

                // Új munkamenet indítása.
                JobRequest jr = new JobRequest();
                jr.create = true;
                jr.jobName = new File(fileName).getName();
                this.getConnection().sendTCP(jr);

            } catch (IOException ex) {
                Dialogs.showErrorMessageDialog(c, ex.getLocalizedMessage());
            }
        }
    }//GEN-LAST:event_newJobButtonActionPerformed

    private void removeJobButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeJobButtonActionPerformed
        JobRequest jr = new JobRequest();
        jr.remove = true;
        this.getConnection().sendTCP(jr);
    }//GEN-LAST:event_removeJobButtonActionPerformed

    private void brightnessContrastButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_brightnessContrastButtonActionPerformed
        // Fényerő és kontraszt beállítása.
        Dimension size = new Dimension(200, 200);

        // Transzformáljuk ha kell.
        BufferedImage lImg;
        synchronized (originalImage) {
            lImg = originalImage.get();
        }
        if (cameraTransformedImageCheckBox.isSelected()) {
            try {
                lImg = ServerCamera.transformImage(lImg, cameraCalibrationPoints);
            } catch (NoninvertibleTransformException | CloneNotSupportedException ex) {
                System.err.println(ex.getLocalizedMessage());
            }
        }

        final BufferedImage imgSrc;
        imgSrc = Scalr.resize(
                lImg, Scalr.Method.ULTRA_QUALITY,
                ((double) size.width / (double) size.height) < ((double) imagePane.getImage().getWidth() / (double) imagePane.getImage().getHeight()) ? Scalr.Mode.FIT_TO_WIDTH : Scalr.Mode.FIT_TO_HEIGHT,
                size.width,
                size.height,
                Scalr.OP_ANTIALIAS);

        JPanel p = new JPanel(new BorderLayout());

        final JLabel imageLabel = new JLabel(new ImageIcon(imgSrc));
        p.add(imageLabel, BorderLayout.CENTER);

        JPanel controlsPanel = new JPanel(new GridLayout(0, 1));
        p.add(controlsPanel, BorderLayout.SOUTH);

        final JSlider bSlider = new JSlider();
        final JSlider cSlider = new JSlider();
        final JSlider fSlider = new JSlider();

        JPanel bPanel = new JPanel(new GridLayout(0, 1));
        final JLabel bLabel = new JLabel();
        bPanel.add(bLabel);
        bSlider.setMaximum(255);
        bSlider.setMinimum(-255);
        bSlider.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent ce) {
                bLabel.setText("Fényerő: " + bSlider.getValue());
                imageLabel.setIcon(new ImageIcon(ColorAdjustment.applyBrightnessAndContrast(imgSrc, (float) cSlider.getValue(), (float) bSlider.getValue())));
            }
        });
        bSlider.setValue(Math.round(this.brightness));
        bLabel.setText("Fényerő: " + Math.round(this.brightness));
        bPanel.add(bSlider);
        controlsPanel.add(bPanel);

        JPanel cPanel = new JPanel(new GridLayout(0, 1));
        final JLabel cLabel = new JLabel();
        cPanel.add(cLabel);
        cSlider.setMaximum(1000);
        cSlider.setMinimum(0);
        cSlider.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent ce) {
                cLabel.setText("Kontraszt: " + cSlider.getValue());
                imageLabel.setIcon(new ImageIcon(ColorAdjustment.applyBrightnessAndContrast(imgSrc, (float) cSlider.getValue(), (float) bSlider.getValue())));
            }
        });
        cSlider.setValue(Math.round(this.contrast));
        cLabel.setText("Kontraszt: " + Math.round(this.contrast));
        cPanel.add(cSlider);
        controlsPanel.add(cPanel);

        JPanel fPanel = new JPanel(new GridLayout(0, 1));
        final JLabel fLabel = new JLabel();
        fPanel.add(fLabel);
        fSlider.setMaximum(255);
        fSlider.setMinimum(-1);
        fSlider.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent ce) {
                fLabel.setText("Fókusz: " + (fSlider.getValue() < 0 ? "Ki" : fSlider.getValue()));
            }
        });
        fSlider.setValue(Math.round(this.focus));
        fLabel.setText("Fókusz: " + (Math.round(this.focus) < 0 ? "Ki" : Math.round(this.focus)));
        fPanel.add(fSlider);
        controlsPanel.add(fPanel);

        Object[] o = {"Ok", "Mégsem"};
        int n = JOptionPane.showOptionDialog(
                this,
                p,
                "Kamera beállításainak módosítása",
                JOptionPane.YES_NO_OPTION,
                JOptionPane.DEFAULT_OPTION,
                null, o, null);

        if (JOptionPane.YES_OPTION == n) {
            CameraColorAdjustmentChangeRequest bccr = new CameraColorAdjustmentChangeRequest();
            bccr.cameraID = this.getCurrentCameraID();
            bccr.brightness = (float) bSlider.getValue();
            bccr.contrast = (float) cSlider.getValue();
            bccr.focus = (float) fSlider.getValue();
            this.getConnection().sendTCP(bccr);
        }
    }//GEN-LAST:event_brightnessContrastButtonActionPerformed

    private void closestSnapButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closestSnapButtonActionPerformed
        MotorControlRequest mcr = new MotorControlRequest();
        mcr.snap = true;
        this.getConnection().sendTCP(mcr);

    }//GEN-LAST:event_closestSnapButtonActionPerformed

    private void rightSnapButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rightSnapButtonActionPerformed
        MotorControlRequest mcr = new MotorControlRequest();
        mcr.snap = true;
        mcr.steps.x = 1;
        this.getConnection().sendTCP(mcr);
    }//GEN-LAST:event_rightSnapButtonActionPerformed

    private void leftSnapButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_leftSnapButtonActionPerformed
        MotorControlRequest mcr = new MotorControlRequest();
        mcr.snap = true;
        mcr.steps.x = -1;
        this.getConnection().sendTCP(mcr);
    }//GEN-LAST:event_leftSnapButtonActionPerformed

    private void upSnapButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_upSnapButtonActionPerformed
        MotorControlRequest mcr = new MotorControlRequest();
        mcr.snap = true;
        mcr.steps.y = -1;
        this.getConnection().sendTCP(mcr);
    }//GEN-LAST:event_upSnapButtonActionPerformed

    private void downSnapButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_downSnapButtonActionPerformed
        MotorControlRequest mcr = new MotorControlRequest();
        mcr.snap = true;
        mcr.steps.y = 1;
        this.getConnection().sendTCP(mcr);
    }//GEN-LAST:event_downSnapButtonActionPerformed

    private void discoverHolesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_discoverHolesButtonActionPerformed

        Object[] oo = {"Igen", "Nem"};
        int nn = JOptionPane.showOptionDialog(
                this,
                "A letapogatás megkezdése után minden előző adat törlésre kerül.\nValóban folytatni kívánja?",
                "Kanava letapogatása",
                JOptionPane.YES_NO_OPTION,
                JOptionPane.WARNING_MESSAGE,
                null, oo, oo[1]);

        if (JOptionPane.YES_OPTION != nn) {
            return;
        }

        // Kanava letapogatása.
        JPanel p = new JPanel(new GridLayout(0, 2));

        JSpinner rowsField = new JSpinner(new SpinnerNumberModel(5, 1, 1000, 1));
        GobelinClientGUI.setSpinnerFocusableSelect(rowsField);
        p.add(new JLabel("Sorok száma:"));
        p.add(rowsField);

        JSpinner columnsField = new JSpinner(new SpinnerNumberModel(3, 1, 1000, 1));
        GobelinClientGUI.setSpinnerFocusableSelect(columnsField);
        p.add(new JLabel("Oszlopok száma:"));
        p.add(columnsField);

        Object[] o = {"Indít", "Mégsem"};
        int n = JOptionPane.showOptionDialog(
                this,
                p,
                "Kanava letapogatása",
                JOptionPane.YES_NO_OPTION,
                JOptionPane.DEFAULT_OPTION,
                null, o, rowsField);

        if (JOptionPane.YES_OPTION == n) {
            MotorControlRequest mcr = new MotorControlRequest();
            mcr.snap = true;
            mcr.discover[0] = (Integer) rowsField.getValue();
            mcr.discover[1] = (Integer) columnsField.getValue();
            this.getConnection().sendTCP(mcr);
        }
    }//GEN-LAST:event_discoverHolesButtonActionPerformed

    private void showHolesToggleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showHolesToggleButtonActionPerformed
        discoveredHolesFrame.setVisible(showHolesToggleButton.isSelected());
    }//GEN-LAST:event_showHolesToggleButtonActionPerformed

    private void stopDiscoveringHolesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_stopDiscoveringHolesButtonActionPerformed
        Object[] oo = {"Igen", "Nem"};
        int nn = JOptionPane.showOptionDialog(
                this,
                "Valóban le kívánja állítani a kanava letapogatását?",
                "Kanava letapogatásának leállítása",
                JOptionPane.YES_NO_OPTION,
                JOptionPane.WARNING_MESSAGE,
                null, oo, oo[1]);

        if (JOptionPane.YES_OPTION == nn) {
            StopDiscoveringHolesRequest sdr = new StopDiscoveringHolesRequest();
            this.getConnection().sendTCP(sdr);
        }
    }//GEN-LAST:event_stopDiscoveringHolesButtonActionPerformed

    private void closeHeadToggleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeHeadToggleButtonActionPerformed
        JToggleButton btn = ((JToggleButton) evt.getSource());

        // Csak akkor küldünk, ha szükséges.
        if (this.contControlCheckBox.isSelected() || (!this.contControlCheckBox.isSelected() && btn.isSelected())) {
            MotorControlRequest mcr = new MotorControlRequest();
            mcr.continuous.z = this.contControlCheckBox.isSelected() && btn.isSelected();
            mcr.steps.z = this.contControlCheckBox.isSelected() || btn.isSelected() ? -1 : 0;
            this.getConnection().sendTCP(mcr);
        }

        // Ha nincs beállítva folyamatos vezérlés, akkor visszaléptetjük a gombot.
        if (!this.contControlCheckBox.isSelected()) {
            btn.setSelected(false);
        }

        // Szemközti irány letiltása.
        if (this.contControlCheckBox.isSelected()) {
            this.openHeadToggleButton.setEnabled(!btn.isSelected());
        }
    }//GEN-LAST:event_closeHeadToggleButtonActionPerformed

    private void openHeadToggleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openHeadToggleButtonActionPerformed
        JToggleButton btn = ((JToggleButton) evt.getSource());

        // Csak akkor küldünk, ha szükséges.
        if (this.contControlCheckBox.isSelected() || (!this.contControlCheckBox.isSelected() && btn.isSelected())) {
            MotorControlRequest mcr = new MotorControlRequest();
            mcr.continuous.z = this.contControlCheckBox.isSelected() && btn.isSelected();
            mcr.steps.z = this.contControlCheckBox.isSelected() || btn.isSelected() ? 1 : 0;
            this.getConnection().sendTCP(mcr);
        }

        // Ha nincs beállítva folyamatos vezérlés, akkor visszaléptetjük a gombot.
        if (!this.contControlCheckBox.isSelected()) {
            btn.setSelected(false);
        }

        // Szemközti irány letiltása.
        if (this.contControlCheckBox.isSelected()) {
            this.closeHeadToggleButton.setEnabled(!btn.isSelected());
        }
    }//GEN-LAST:event_openHeadToggleButtonActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton brightnessContrastButton;
    private javax.swing.JToggleButton cameraCalibrationToggleButton;
    private javax.swing.JCheckBox cameraLightCheckBox;
    private javax.swing.JCheckBox cameraTransformedImageCheckBox;
    private javax.swing.ButtonGroup camerasGroup;
    private javax.swing.JPanel camerasPanel;
    private javax.swing.JToggleButton closeHeadToggleButton;
    private javax.swing.JButton closestSnapButton;
    private javax.swing.JCheckBox contControlCheckBox;
    private javax.swing.JPanel controlButtonsPanel;
    private javax.swing.JPanel controlPanel;
    private javax.swing.JLabel coreTemperatureLabel;
    private javax.swing.JButton discoverHolesButton;
    private javax.swing.JButton downSnapButton;
    private javax.swing.JToggleButton downStepToggleButton;
    private javax.swing.JPanel informationPanel;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JPanel jPanel10;
    private javax.swing.JPanel jPanel11;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JPanel jPanel5;
    private javax.swing.JPanel jPanel6;
    private javax.swing.JPanel jPanel7;
    private javax.swing.JPanel jPanel8;
    private javax.swing.JPanel jPanel9;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JLabel jobDataLabel;
    private javax.swing.JPanel jobPanel;
    private javax.swing.JLabel jobProgressLabel;
    private javax.swing.JButton leftSnapButton;
    private javax.swing.JToggleButton leftStepToggleButton;
    private javax.swing.JPanel lightsPanel;
    private javax.swing.JSplitPane mainSplitPane;
    private javax.swing.JLabel motorLocationsLabel;
    private javax.swing.JToggleButton needleCalibrationButton;
    private javax.swing.JPanel needleCalibrationPanel;
    private javax.swing.JButton newJobButton;
    private javax.swing.JToggleButton openHeadToggleButton;
    private javax.swing.JPanel optionsPanel;
    private javax.swing.JScrollPane optionsScrollPane;
    private javax.swing.JLabel receivingDataLabel;
    private javax.swing.JButton removeJobButton;
    private javax.swing.JButton rightSnapButton;
    private javax.swing.JToggleButton rightStepToggleButton;
    private javax.swing.JLabel serverStateLabel;
    private javax.swing.JToggleButton showHolesToggleButton;
    private javax.swing.JPanel snapButtonsPanel;
    private javax.swing.JButton stopDiscoveringHolesButton;
    private javax.swing.JButton upSnapButton;
    private javax.swing.JToggleButton upStepToggleButton;
    private javax.swing.JCheckBox viewAllMarksCheckBox;
    private javax.swing.JCheckBox viewHoleCalcMarksCheckBox;
    private javax.swing.JCheckBox viewHoleFoundMarksCheckBox;
    private javax.swing.JCheckBox viewLineMarksCheckBox;
    private javax.swing.JCheckBox viewNeedleMarkCheckBox;
    private javax.swing.JPanel viewsPanel;
    // End of variables declaration//GEN-END:variables
}
